package belf.migrate.engine.job.structure.helper;

import belf.migrate.api.exception.CatalogException;
import belf.migrate.api.table.schema.Catalog;
import belf.migrate.api.table.schema.TablePath;
import belf.migrate.api.taskconf.JobContext;
import belf.migrate.api.type.DbObjectType;
import belf.migrate.api.type.LogLevelType;
import belf.migrate.api.util.PostLog;
import belf.migrate.api.job.Job;
import belf.migrate.engine.job.JobResult;
import belf.migrate.engine.job.JobResultItem;
import belf.migrate.api.taskconf.Task;
import belf.migrate.api.util.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.Date;
import java.util.List;

import static belf.migrate.api.job.JobCode.*;

@Slf4j
public class DropTriggerTool extends NonTableTool {
    public DropTriggerTool(Job job) {
        super(job);
    }

    public DropTriggerTool(Job job, JobContext jobContext) {
        super(job, jobContext);
    }

    @Override
    public JobResult run() {
        PostLog.sendLogModel(
                job.getJobId(),
                job.getTask().getTaskType().getName(),
                "删除触发器开始！",
                LogLevelType.INFO.getType(),
                EXECUTING,
                jobContext.getProgress());
        JobResult jobResult = new JobResult(SUCCESS, "删除选中的触发器成功");
        Catalog sinkCatalog = jobContext.getSinkCatalog();

        try {
            List<String> triggerNames; //待创建的触发器名称列表
            // 若限定了要处理的触发器名称
            if (job.getMissions() != null && !job.getMissions().isEmpty()) {
                triggerNames = job.getMissions();
            } else {
                triggerNames = sinkCatalog.listTriggerNames(jobContext.getTaskConf().getSinkConf().getDatabaseName(),
                        jobContext.getTaskConf().getSinkConf().getSchemaName());
            }

            if (null != triggerNames) {
                for (String triggerName : triggerNames) {
                    jobContext.addProgress(DbObjectType.TRIGGER.getTypeName(), triggerNames.size());
                    JobResultItem jobResultItem = process(triggerName, sinkCatalog);
                    jobResult.addItem(jobResultItem);
                    if (jobResultItem.getCode() != SUCCESS
                            && job.getTask().getTaskPolicy() == Task.TaskPolicy.ERROR_STOP) {
                        break;  //创建表遇到错误即返回
                    }
                }
            }
        } catch (CatalogException e) {
            e.printStackTrace();
        }
        if (jobResult.getFailtures() > 0) {
            jobResult.setCode(DROP_TRIGGER_ERROR);
            jobResult.setMessage("删除选中的触发器失败");
            log.error("Drop Some Triggers Of {} Failed.", jobContext.getValidSinkDatabase());
        } else {
            log.info("Drop All Triggers Of {} Successfully.", jobContext.getValidSinkDatabase());
        }

        PostLog.sendLogModel(
                job.getJobId(),
                job.getTask().getTaskType().getName(),
                "删除触发器结束！",
                LogLevelType.INFO.getType(),
                EXECUTING,
                jobContext.getProgress());
        return jobResult;
    }
    
    private JobResultItem process(String triggerName, Catalog sinkCatalog) {
        String startTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
        TablePath triggerPath = TablePath.of(jobContext.getTaskConf().getSinkConf().getDatabaseName(),
                jobContext.getTaskConf().getSinkConf().getSchemaName(),
                triggerName,
                getSinkQualifiersModel());
        try {
            boolean result = sinkCatalog.dropTrigger(triggerPath);
            if (!result) {
                PostLog.sendLogModel(
                        job.getJobId(),
                        job.getTask().getTaskType().getName(),
                        "目标库" + "删除触发器失败：" + triggerName,
                        LogLevelType.ERROR.getType(),
                        EXECUTING,
                        jobContext.getProgress());
                String endTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
                return new JobResultItem(triggerName,
                        triggerPath.getCaseTableName(),
                        DROP_TRIGGER_ERROR,
                        "目标库" + "删除触发器失败：" + triggerName,
                        "",
                        DbObjectType.TRIGGER.getTypeName(),
                        startTime,
                        endTime,
                        null,
                        sinkCatalog.getDropTriggerSql(triggerPath));
            }
        } catch (CatalogException e) {
            e.printStackTrace();
            PostLog.sendLogModel(
                    job.getJobId(),
                    job.getTask().getTaskType().getName(),
                    "目标库" + "删除触发器失败：" + triggerName,
                    LogLevelType.ERROR.getType(),
                    EXECUTING,
                    jobContext.getProgress());
            String endTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
            return new JobResultItem(triggerName,
                    triggerPath.getCaseTableName(),
                    DROP_TRIGGER_ERROR,
                    "目标库" + "删除触发器失败：" + triggerName,
                    ExceptionUtils.toString(e),
                    DbObjectType.TRIGGER.getTypeName(),
                    startTime,
                    endTime,
                    null,
                    sinkCatalog.getDropTriggerSql(triggerPath));
        }
        PostLog.sendLogModel(
                job.getJobId(),
                job.getTask().getTaskType().getName(),
                "删除建触发器" + triggerName + "成功",
                LogLevelType.INFO.getType(),
                EXECUTING,
                jobContext.getProgress());

        JobResultItem jobResultItem = new JobResultItem(
                triggerName,
                triggerPath.getCaseTableName(),
                SUCCESS,
                "删除建触发器" + triggerName + "成功");
        jobResultItem.setSinkDdl(sinkCatalog.getDropTriggerSql(triggerPath));
        return jobResultItem;
    }
}
